package com.hitechbangla.fctu.base.aircraft.command;

import com.hitechbangla.fctu.base.Location;
import com.hitechbangla.fctu.utility.enumall.CommandType;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.hitechbangla.fctu.utility.enumall.*;
import com.hitechbangla.fctu.base.aircraft.Aircraft;
import com.hitechbangla.fctu.base.aircraft.AircraftState;
import com.hitechbangla.fctu.base.aircraft.AircraftTurnDegree;
import com.hitechbangla.fctu.base.aircraft.AircraftType;
import java.io.Serializable;

/**
 *
 * @author deb kanti
 */
public class AircraftCommandState implements Serializable 
{   
    //variables for turn command
    private TurnDirection turnDirection; // left or right
    private TurnDegree turnDegree; // slack, tight or normal
    private float headingAngle; // this is the target heading, except Type2, where this is the angle that will be added to current heading
    private static float headingAngleStatic;
    
    // variables for height change command
    private int expedite;
    private AircraftHeightChangeType aircraftHeightChangeType; // climb, descend or make
    private double aircraftHeightTarget;;
    private float climbRate;
    //
    private CommandType commandType;  // Type1, Type2, etc
    private String rawCommand; // the command that comes from keyboard
    private Aircraft aircraft; // this is the aircraft upon which the command will be executed
    
    private CommandStatus commandStatus;
    private float speedNew;
    
    
    public AircraftCommandState(String rawCommand, Aircraft aircraft)
    {
        this.rawCommand = rawCommand;
        this.aircraft = aircraft;        
    } // end of constructor 
            
            
    public void executeCommand()
    {
        compareWithCommandRegEx(rawCommand); //        
        splitRawCommand();    
        this.aircraft.executeCommand(); // this calls the aircraft to execute command         
    } // end of executeCommand function
    
    
    // this function splits the raw command, and assigns heading angle, turn direction and turn degree variable
    private void splitRawCommand()
    {
        Pattern patternRegEx = Pattern.compile(getCommandType().getRegEx());
        Matcher matcher = patternRegEx.matcher(rawCommand);
        
        if(matcher.matches())
        {
            if(getCommandType() == CommandType.Type1 || getCommandType() == CommandType.Type2 )
            {                
                turnDegree = getCommandType().getDegreeFromRegEx(matcher.group(1));                
                turnDirection = getCommandType().getDirectionFromRegEx(matcher.group(2));
                headingAngle = Float.parseFloat(matcher.group(3));      
		headingAngleStatic = headingAngle;
            }           
	    
	    else if(getCommandType() == CommandType.Type7)
            {
                turnDegree = getCommandType().getDegreeFromRegEx(matcher.group(1));
                turnDirection = getCommandType().getDirectionFromRegEx(matcher.group(2));		
		headingAngle = headingAngleStatic;
            }
            
            else if(getCommandType() == CommandType.Type3)
            {
                turnDegree = getCommandType().getDegreeFromRegEx(matcher.group(1));                
                headingAngle = Float.parseFloat(matcher.group(2));
            }
            
            else if(getCommandType() == CommandType.Type4)
            {
                // this is roll command, so no command  variable
            }
            
            else if(getCommandType() == CommandType.Type5)
            {
                turnDegree = getCommandType().getDegreeFromRegEx(matcher.group(1));                
                headingAngle = Float.parseFloat(matcher.group(2));
            }
            
            else if(getCommandType() == CommandType.Type6)
            {
                turnDegree = getCommandType().getDegreeFromRegEx(matcher.group(1));
                turnDirection = getCommandType().getDirectionFromRegEx(matcher.group(2));
            }
            
	    
	    
            else if(getCommandType() == CommandType.Type8)
            {
                String tempExpedite = matcher.group(1);
                if(tempExpedite.equals(""))
                {
                    expedite = 1;
                }
                else
                {
                    expedite = Integer.parseInt(matcher.group(1));
                }
            
            
                
                String tempHeightChangeType = matcher.group(2);
                
                float heightChange = Float.parseFloat(matcher.group(3));
                
                if(tempHeightChangeType.equals("c"))
                {
                    aircraftHeightChangeType = AircraftHeightChangeType.CLIMB;
                    double heightTarget = aircraft.getAircraftState().getLocation().getZ() +  heightChange;
                    setAircraftHeightTarget(heightTarget);
                    setClimbRate(aircraft.getAircraftType().getClimbRate());
                }
                else if(tempHeightChangeType.equals("d"))
                {
                    aircraftHeightChangeType = AircraftHeightChangeType.DESCEND;
                    double heightTarget = aircraft.getAircraftState().getLocation().getZ() -  heightChange;
                    setAircraftHeightTarget(heightTarget);
                    setClimbRate(-aircraft.getAircraftType().getClimbRate());
                }
                else if(tempHeightChangeType.equals("m"))
                {
                    aircraftHeightChangeType = AircraftHeightChangeType.MAKE;
                    setAircraftHeightTarget(heightChange);
                    
                    if(getAircraftHeightTarget()>aircraft.getAircraftState().getLocation().getZ())
                    {
                        setClimbRate(aircraft.getAircraftType().getClimbRate());
                    }
                    else
                    {
                        setClimbRate(-aircraft.getAircraftType().getClimbRate());
                    }                    
                }
            } 
            
         else if(getCommandType() == CommandType.Type9)
         {                
            this.speedNew = Float.parseFloat(matcher.group(2));
                 /*
                 //float speedTarget = aircraft.getAircraftState().getLocation().getZ() +  speedChange;
                 aircraft.getAircraftState().setSpeed(speedNew);
                 */
                // float sppedTargetNegative = aircraft.getAircraftState().getSpeed() - speedChange;
         } 
            
            
            
        }
    } // end of splitRawCommand function
    
   
   // this function compares all the turn commands with current command using regEx.. 
   private void compareWithCommandRegEx(String command)
   {
       for(CommandType tempCommandType: CommandType.values())
       {
           Pattern patternRegEx = Pattern.compile(tempCommandType.getRegEx());
           Matcher matcher = patternRegEx.matcher(command);
           
           if(matcher.matches())
           {
               this.commandType = tempCommandType;              ////System.out.println(commandType.toString());               
           }           
       }       
   } // end of compareWithCommandRegEx function

    /**
     * @return the turnDirection
     */
    public TurnDirection getTurnDirection() 
    {
        return turnDirection;
    }

    /**
     * @return the turnDegree
     */
    public TurnDegree getTurnDegree() 
    {
        return turnDegree;
    }

    /**
     * @return the headingAngle
     */
    public float getHeadingAngle() 
    {
        return headingAngle;
    }

    /**
     * @return the commandType
     */
    public CommandType getCommandType() {
        return commandType;
    }

    /**
     * @return the expedite
     */
    public int getExpedite() {
        return expedite;
    }

    /**
     * @param expedite the expedite to set
     */
    public void setExpedite(int expedite) {
        this.expedite = expedite;
    }

    /**
     * @return the aircraftHeightChangeType
     */
    public AircraftHeightChangeType getAircraftHeightChangeType() {
        return aircraftHeightChangeType;
    }

    /**
     * @param aircraftHeightChangeType the aircraftHeightChangeType to set
     */
    public void setAircraftHeightChangeType(AircraftHeightChangeType aircraftHeightChangeType) {
        this.aircraftHeightChangeType = aircraftHeightChangeType;
    }

    /**
     * @return the aircraftHeightChange
     */
    

    /**
     * @return the climbRate
     */
    public float getClimbRate() 
    {
        return climbRate;
    }

    /**
     * @param climbRate the climbRate to set
     */
    public void setClimbRate(float climbRate) {
        this.climbRate = climbRate;
    }

    /**
     * @return the commandStatus
     */
    public CommandStatus getCommandStatus() 
    {
        if(getCommandType() == CommandType.Type1 || getCommandType() == CommandType.Type2 || getCommandType() == CommandType.Type3 || getCommandType() == CommandType.Type4 || getCommandType() == CommandType.Type5 || getCommandType() == CommandType.Type6 || getCommandType() == CommandType.Type7)
        {
            return CommandStatus.TURN;
        }
        else if (getCommandType() == CommandType.Type8)
        {
            return CommandStatus.HEIGHT_CHANGE;
        }
        else if (getCommandType() == commandType.Type9)
        {
            return commandStatus.SPEED_CHANGE;
        }
        else
        {
            return CommandStatus.NONE;
        }
    }

    /**
     * @param commandStatus the commandStatus to set
     */
    public void setCommandStatus(CommandStatus commandStatus) {
        this.commandStatus = commandStatus;
    }

    /**
     * @return the aircraftHeightTarget
     */
    public double getAircraftHeightTarget() {
        return aircraftHeightTarget;
    }

    /**
     * @param aircraftHeightTarget the aircraftHeightTarget to set
     */
    public void setAircraftHeightTarget(double aircraftHeightTarget) {
        this.aircraftHeightTarget = aircraftHeightTarget;
    }

    /**
     * @return the climbRate
     */
    
    public static void main(String a[])
    {
        AircraftType aircraftType1 = new AircraftType("F16", 360, 50, 2000, new AircraftTurnDegree(1.1f,6.0f, 2.2f),0.7f );
        //AircraftType aircraftType2 = new AircraftType("Mig29", 600, 100, 3000, new AircraftTurnDegree(3f,8.0f, 4f),.2f);
        
        AircraftState aircraftState1 = new AircraftState("111",new Location(41,80,0),0,1000, 2000);
        //AircraftState aircraftState2 = new AircraftState("222",new Location(10,10,5),30,1000, 2000);
        
        Aircraft aircraft = new Aircraft(aircraftState1, aircraftType1);////System.out.println(aircraft.getWind().getName());
	
	/*
        for(int i=0;i<100;i++)
        {
            aircraft.update(1000);
            //System.out.println("from aircraft command state: x " + aircraft.getAircraftState().getLocation().getX() + ", y " + aircraft.getAircraftState().getLocation().getY() + ", heading " + aircraft.getAircraftState().getHeading());        
        }
	*/
	
	aircraft.executeCommand("111l345");
	//aircraft.executeCommand("111sr");
        //aircraft.executeCommand("111s2000");
	aircraft.update(1000);
    }

    /**
     * @return the speedNew
     */
    public float getSpeedNew() {
        return speedNew;
    }
    
}

    




